home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / GENetReleaseƒ / GEDemo / GEDemo.c < prev    next >
C/C++ Source or Header  |  1994-02-15  |  16KB  |  760 lines

  1. /*
  2.     GEDemo.c
  3.     
  4.     Demo program for Graphic Elements library
  5.     
  6.     11/1/93
  7.     
  8.     Al Evans
  9. */
  10.  
  11. #ifdef applec
  12. #ifndef PRELOAD
  13. #pragma load "::ToolKit.precompile"
  14. #define PRELOAD
  15. #endif
  16. #else
  17. #include <QDOffscreen.h>
  18. #endif
  19.  
  20. #include <Timer.h>
  21. #include <GestaltEqu.h>
  22.  
  23. #include "GUtilities.h"
  24. #include "GraphElements.h"
  25. #include "Sensors.h"
  26. #include "Cannon.h"
  27. #include "Walk.h"
  28. #include "Pogo.h"
  29. #include "Sign.h"
  30. #include "Meter.h"
  31. #include "Grabber.h"
  32.  
  33. //define HISTOGRAM to collect times history
  34. #undef HISTOGRAM
  35.  
  36. #ifdef HISTOGRAM
  37. #include "StdIO.h"
  38. #endif
  39.  
  40. //define PERFORMANCE to collect profiling data
  41. #undef PERFORMANCE
  42. #ifdef PERFORMANCE
  43. #include <Perf.h>
  44. #endif
  45.  
  46.  
  47. //Menu Commands
  48.  
  49. #define    rMenuBar                128        /* application's menu bar */
  50.  
  51. #define    mApple                    128        /* Apple menu */
  52. #define    iAbout                    1
  53.  
  54. #define    mFile                    129        /* File menu */
  55. #define    iQuit                    1
  56.  
  57. #define    mEdit                    130        /* Edit menu */
  58. #define    iUndo                    1
  59. #define    iCut                    3
  60. #define    iCopy                    4
  61. #define    iPaste                    5
  62. #define    iClear                    6
  63.  
  64. #define mSpecial                131
  65. #define iShoot                    1
  66. #define iSingleFrame            2
  67. #define iSignText                3
  68. #define iSpeed                    4
  69. #define iGrabber                5
  70.  
  71.  
  72. #define    rAboutDialog    228        
  73. #define rUserAlert        129
  74. #define rSetTextDialog    135
  75. #define rFrameRateDialog 130
  76. #define rSpeedDialog    131
  77.  
  78. //Resource numbers of graphic PICTs
  79. #define    rBrickPic 200
  80.  
  81. //Number of master pointer blocks needed
  82.  
  83. #define masterBlocksNeeded 10
  84.  
  85. //Globals
  86.  
  87. #ifdef PERFORMANCE
  88. TP2PerfGlobals        thePGlobals;
  89. #endif
  90.  
  91. Boolean        gFinished;
  92. WindowPtr    gAnimWindow;
  93. Boolean        gSingleFrame = false;
  94. Boolean        gDoOne = false;
  95.  
  96. //Performance measurement
  97.  
  98. #define thirtySeconds 30L * 1000 * 1000        //µsec for timers -- never time out
  99.  
  100. TMTask    gTTimeTask, gATimeTask;
  101. unsigned long gTotalTime = 0, gAnimTime = 0;
  102.  
  103. #ifdef HISTOGRAM
  104. long    animTimes[100];
  105. long    mainTimes[100];
  106. #endif
  107.  
  108. //Forward declarations
  109.  
  110. #ifdef applec
  111. extern void _DataInit();    //reference so that we can unload it
  112. #endif
  113.  
  114. Boolean Initialize( void );
  115. void Shutdown(void);
  116. void EventLoop( void );
  117.  
  118. main()
  119. {
  120. #ifdef applec
  121.     UnloadSeg((Ptr) _DataInit);
  122. #endif
  123.     MaxApplZone();
  124.     if ( Initialize() )
  125.         EventLoop();
  126.     Shutdown();
  127. }
  128.  
  129.  
  130. //Initialization
  131.  
  132. Boolean AdequateSystem(void)
  133. {
  134.     OSErr        err;
  135.     long        response;
  136.     Boolean        ok;
  137.     
  138.     //We need 68020 or better
  139.     err = Gestalt(gestaltProcessorType, &response);
  140.     ok = (!err) & (response >= gestalt68020);
  141.     
  142.     //We need System 7 or later
  143.     err = Gestalt(gestaltSystemVersion, &response);
  144.     ok = (!err) & (((response & 0xFFFF) / 256) >= 7);
  145.     
  146.     //We need color QD & offscreen GWorlds
  147.     err = Gestalt(gestaltQuickdrawVersion, &response);
  148.     ok = ok & (!err) & (response >= gestalt32BitQD);
  149.     err = Gestalt(gestaltQuickdrawFeatures, &response);
  150.     ok = ok & (!err) & (response >= 3);         //hasColor & deep GWorlds
  151.     
  152.     return ok;
  153.     
  154. }
  155.  
  156. //Make window centered on main graphic device
  157. WindowPtr MakeWindow(short wHSize, short wVSize)
  158. {
  159.     GDHandle    mainDevice;
  160.     Rect        devRect;
  161.     short        hOffst, vOffst;
  162.     Rect        windRect;
  163.     
  164.     mainDevice = GetMainDevice();
  165.     devRect = (**mainDevice).gdRect;
  166.     hOffst = (devRect.right - devRect.left - wHSize) / 2;
  167.     if (hOffst < 0) hOffst = 0;
  168.     vOffst = (devRect.bottom - devRect.top - wVSize) / 2;
  169.     if (vOffst < 0 ) vOffst = 0;
  170.     windRect.left = hOffst;
  171.     windRect.right = hOffst + wHSize;
  172.     windRect.top = vOffst;
  173.     windRect.bottom = vOffst + wVSize; 
  174.     
  175.     return NewCWindow(nil, &windRect, "\pAnimation Demo", false, documentProc,
  176.                         (WindowPtr) -1L, false, 0L);
  177. }
  178.  
  179.  
  180. void DoNothing( void )
  181. {
  182. }
  183.  
  184. void InitPerformanceTiming(void)
  185. {
  186.     //Init Timers
  187.     gTTimeTask.tmAddr = (TimerProcPtr) DoNothing;
  188.     gTTimeTask.tmWakeUp = 0;
  189.     gTTimeTask.tmReserved = 0;
  190.     
  191.     gATimeTask.tmAddr =  (TimerProcPtr) DoNothing;
  192.     gATimeTask.tmWakeUp = 0;
  193.     gATimeTask.tmReserved = 0;
  194.     
  195. }
  196.  
  197. Boolean LoadBackground(GEWorldPtr world)
  198. {
  199.     GrafElPtr    bkg;
  200.     if (bkg = NewBasicPICT(world, 'BKG ', 1, rBrickPic, srcCopy, 0, 0))
  201.         return true;
  202.     return false;
  203. }
  204.  
  205. Boolean Initialize(void)
  206. {
  207.     Rect        animRect;
  208.     GEWorldPtr    animWorld;
  209. #ifdef HISTOGRAM
  210.     short    count;
  211. #endif
  212.     
  213.     gFinished = false;
  214.     
  215.     InitSystem(masterBlocksNeeded);
  216.     
  217.     
  218.     if (!AdequateSystem()) {
  219.         TellUser("\pSorry, more powerful system required", 0);
  220.         return false;
  221.     }
  222.     if (!LoadMenus(rMenuBar)) {
  223.         TellUser("\pCould not load menus", 0);
  224.         return false;
  225.     }
  226.     
  227.     //DebugStr("\pInitializing...");
  228.     //Create window and install animation
  229.     if (gAnimWindow = MakeWindow(512, 364)){
  230.         animRect.left = 0;
  231.         animRect.right = 512;
  232.         animRect.top = 0;
  233.         animRect.bottom = 364;
  234.         if (animWorld = NewGEWorld((CWindowPtr) gAnimWindow, &animRect, nil))
  235.             SetWRefCon(gAnimWindow, (long) animWorld);
  236.         else {
  237.             TellUser("\pCould not install animation in window", 0);
  238.             return false;
  239.         }
  240.     }
  241.     else {
  242.         TellUser("\pCould not create window", 0);
  243.         return false;
  244.     }
  245.     
  246.     InitPerformanceTiming();
  247.     
  248.     //Load graphics
  249.     
  250.     if (!LoadBackground((GEWorldPtr) GetWRefCon(gAnimWindow))) {
  251.         TellUser("\pCould not load background", 0);
  252.         return false;
  253.     }
  254.     if (!LoadCannonScene((GEWorldPtr) GetWRefCon(gAnimWindow))) {
  255.         TellUser("\pCould not load cannon scene", 0);
  256.         return false;
  257.     }
  258.     
  259.     if (!LoadBalconyScene((GEWorldPtr) GetWRefCon(gAnimWindow))) {
  260.         TellUser("\pCould not load animated walk", 0);
  261.         return false;
  262.     }
  263.     
  264.     if (!LoadPogoScene((GEWorldPtr) GetWRefCon(gAnimWindow))) {
  265.         TellUser("\pCould not load pogo stick", 0);
  266.         return false;
  267.     }
  268.     
  269.     if (!LoadSignScene((GEWorldPtr) GetWRefCon(gAnimWindow))) {
  270.         TellUser("\pCould not load sign", 0);
  271.         return false;
  272.     }
  273.     
  274.     if (!LoadUsageMeterScene((GEWorldPtr) GetWRefCon(gAnimWindow))) {
  275.         TellUser("\pCould not load usage meter", 0);
  276.         return false;
  277.     }
  278.     if (!MakeGrabber((GEWorldPtr) GetWRefCon(gAnimWindow))) {
  279.         TellUser("\pCould not create grabber", 0);
  280.         return false;
  281.     }
  282.     
  283. #ifdef HISTOGRAM
  284.     for (count = 0; count < 100; count++) {
  285.         animTimes[count] = 0;
  286.         mainTimes[count] = 0;
  287.     }
  288. #endif
  289.     
  290. #ifdef PERFORMANCE
  291.     thePGlobals = nil;
  292.     if (!InitPerf( &thePGlobals, 10, 8, true, true, "\pCODE", 0, "\p", false, 0L, 0L, 0) ){
  293.         TellUser("\pCould not initialize profiling", 0);
  294.         return false;
  295.     }
  296. #endif
  297.     
  298.     //Turn animation on and show window
  299.     ActivateWorld((GEWorldPtr) GetWRefCon(gAnimWindow), true);
  300.     ShowWindow(gAnimWindow);
  301.     
  302. }
  303.  
  304. #ifdef HISTOGRAM
  305. void DumpHistograms(void)
  306. {
  307.     short    count;
  308.     FILE*    dump;
  309.     
  310.     dump = fopen("HistoDump", "w");
  311.     for (count = 0; count < 100; count++) 
  312.         fprintf(dump, "%d\t%d\t%d\n", count, mainTimes[count], animTimes[count]);
  313.     fflush(dump);
  314.     fclose(dump);
  315. }
  316. #endif
  317.  
  318. void Shutdown(void)
  319. {
  320. #ifdef PERFORMANCE
  321.     OSErr err;
  322. #endif
  323.     //Release system resources
  324.     
  325. #ifdef HISTOGRAM
  326.     DumpHistograms();
  327. #endif
  328. #ifdef PERFORMANCE
  329.     err = PerfDump(thePGlobals, "\pPerform.out", false, 0);
  330. #endif
  331.     StopGETimer((GEWorldPtr) GetWRefCon(gAnimWindow));
  332.     ExitToShell();
  333. }
  334.  
  335. #ifdef HISTOGRAM
  336.  
  337. void RunMeterAnimation(void)
  338. {
  339.     static short    setting = 0;
  340.     short            thisSetting;
  341.     if ((gTotalTime - gAnimTime) < 100)
  342.         mainTimes[(gTotalTime - gAnimTime)]++;
  343.     else
  344.         mainTimes[99]++;
  345.     if (gAnimTime < 100)
  346.         animTimes[gAnimTime]++;
  347.     else
  348.         animTimes[99]++;
  349.     
  350.     if (gTotalTime == 0) gTotalTime = 1;
  351.     thisSetting = (gAnimTime * 100) / gTotalTime;
  352.     if (thisSetting == setting)
  353.         return;
  354.     if (thisSetting > setting)
  355.         setting++;
  356.     else
  357.         if (thisSetting < setting)
  358.             setting--;
  359.     SetMeterReading((GEWorldPtr) GetWRefCon(gAnimWindow), setting);
  360. }    
  361.  
  362. #else
  363.  
  364. void RunMeterAnimation(void)
  365. {
  366.     static short    setting = 0;
  367.     short            thisSetting;
  368.     
  369.     if (gTotalTime == 0) gTotalTime = 1;
  370.     thisSetting = (gAnimTime * 100) / gTotalTime;
  371.     if (thisSetting == setting)
  372.         return;
  373.     if (thisSetting > setting)
  374.         setting++;
  375.     else
  376.         if (thisSetting < setting)
  377.             setting--;
  378.     SetMeterReading((GEWorldPtr) GetWRefCon(gAnimWindow), setting);
  379.     
  380. }
  381. #endif
  382.  
  383. void DoTimingLoop(void)
  384. {
  385. }
  386.  
  387. pascal Boolean SignFilter(DialogPtr dialog, EventRecord *event, short *item)
  388. {
  389. #pragma unused (dialog)
  390.  
  391. TEHandle    text;
  392.     
  393.     if ((event->what == keyDown) || (event->what == autoKey)) {
  394.         switch (event->message & charCodeMask) {
  395.         case 0x0d:
  396.         case 0x03:
  397.             *item = ok;
  398.             return true;
  399.             break;
  400.         case 0x1b:
  401.             *item = cancel;
  402.             return true;
  403.             break;
  404.         default:
  405.             text = ((DialogPeek) dialog)->textH;
  406.             //If 15 chars already and trying to insert
  407.             if ((GetHandleSize((**text).hText) > 14) && ((**text).selStart == (**text).selEnd)) {
  408.                 SysBeep(3);
  409.                 *item = 4;
  410.                 return true;
  411.             }
  412.             else
  413.                 return false;
  414.         }
  415.     }
  416.     else return false;
  417. }
  418.  
  419. void DoSetSignText( void )
  420. {
  421.     DialogPtr     sgnDialog;
  422.     short        itemType;
  423.     Handle        item;
  424.     Rect        okRect;
  425.     Rect        itemRect;
  426.     short        itemHit;
  427.     Str255        signText;
  428.     
  429.     sgnDialog = GetNewDialog(rSetTextDialog, nil, (WindowPtr) -1L);
  430.     GetDItem(sgnDialog, ok, &itemType, &item, &okRect);
  431.     GetDItem(sgnDialog, 4, &itemType, &item, &itemRect);
  432.     GetSignText(signText);
  433.     SetIText(item, signText);
  434.     InsetRect(&okRect, -4, -4);
  435.     ShowWindow(sgnDialog);
  436.     SetPort( (GrafPtr) sgnDialog);
  437.     PenSize(3, 3);
  438.     FrameRoundRect(&okRect, 16, 16);
  439.     SelIText(sgnDialog, 4, 0, 32767);
  440.     do
  441.         ModalDialog(SignFilter, &itemHit);
  442.     while ( (itemHit != ok) && (itemHit != cancel) );
  443.     if (itemHit == ok) {
  444.         GetIText(item, signText);
  445.         SetSignText((GEWorldPtr) GetWRefCon(gAnimWindow), signText);
  446.     }
  447.     
  448.     DisposDialog(sgnDialog);
  449. }
  450.  
  451. void DoSetSpeed( void )
  452. {
  453.     DialogPtr spdDialog;
  454.     short        itemType;
  455.     Handle        item;
  456.     Rect        okRect;
  457.     Rect        itemRect;
  458.     short        itemHit;
  459.     Str255        tmrSpdStr;
  460.     long        timerSpeed;
  461.     
  462.     spdDialog = GetNewDialog(rSpeedDialog, nil, (WindowPtr) -1L);
  463.     GetDItem(spdDialog, ok, &itemType, &item, &okRect);
  464.     GetDItem(spdDialog, 4, &itemType, &item, &itemRect);
  465.     timerSpeed = GetGETimerRate((GEWorldPtr) GetWRefCon(gAnimWindow));
  466.     timerSpeed = (100 * timerSpeed) >> 16;
  467.     NumToString( (long) timerSpeed, tmrSpdStr);
  468.     SetIText(item, tmrSpdStr);
  469.     InsetRect(&okRect, -4, -4);
  470.     ShowWindow(spdDialog);
  471.     SetPort( (GrafPtr) spdDialog);
  472.     PenSize(3, 3);
  473.     FrameRoundRect(&okRect, 16, 16);
  474.     SelIText(spdDialog, 4, 0, 32767);
  475.     do
  476.         ModalDialog(nil, &itemHit);
  477.     while ( (itemHit != ok) && (itemHit != cancel) );
  478.     if (itemHit == ok) {
  479.         GetIText(item, tmrSpdStr);
  480.         StringToNum(tmrSpdStr, &timerSpeed);
  481.         timerSpeed = (timerSpeed << 16) / 100;
  482.         SetGETimerRate((GEWorldPtr) GetWRefCon(gAnimWindow), timerSpeed);
  483.     }
  484.     
  485.     DisposDialog(spdDialog);
  486. }
  487.  
  488. pascal Boolean AboutFilter(DialogPtr dialog, EventRecord *event, short *item)
  489. {
  490. #pragma unused (dialog)
  491.     DoWorldUpdate((GEWorldPtr) GetWRefCon(gAnimWindow), false);
  492.     if ((event->what == mouseDown) || (event->what == keyDown)) {
  493.         *item = ok;
  494.         return true;
  495.     }
  496.     else return false;
  497. }
  498.  
  499. void DoAboutBox(void)
  500. {
  501.     DialogPtr    aboutDialog;
  502.     short        itemHit;
  503.     
  504.     aboutDialog = GetNewDialog(rAboutDialog, nil, (WindowPtr) -1L);
  505.     ModalDialog(AboutFilter, &itemHit);
  506.     DisposDialog(aboutDialog);
  507. }
  508.  
  509. //Event Handling
  510.  
  511. void EventLoop( void )
  512. {
  513.     Boolean        gotEvent;
  514.     EventRecord    event;
  515.     
  516.     void DoEvent (EventRecord *event);
  517.     void AdjustCursor( void);
  518.     
  519.     do {
  520.         InsTime( (QElemPtr) &gTTimeTask);
  521.         InsTime( (QElemPtr) &gATimeTask);
  522.         PrimeTime( (QElemPtr) &gTTimeTask, -thirtySeconds);
  523.         if (!gSingleFrame || gDoOne) {
  524.             PrimeTime( (QElemPtr) &gATimeTask, -thirtySeconds);
  525.             
  526. #ifdef PERFORMANCE
  527.             (void) PerfControl(thePGlobals, true);
  528. #endif
  529.  
  530.             DoWorldUpdate((GEWorldPtr) GetWRefCon(gAnimWindow), false);
  531.             
  532. #ifdef PERFORMANCE
  533.             (void) PerfControl(thePGlobals, false);
  534. #endif
  535.             RmvTime( (QElemPtr) &gATimeTask);
  536.             gAnimTime = (thirtySeconds + gATimeTask.tmCount) / 1000;
  537.             gDoOne = false;
  538.         }
  539.         AdjustCursor();
  540.         if (gotEvent = WaitNextEvent(everyEvent, &event, 0L, nil)) 
  541.             DoEvent(&event);
  542.         RmvTime( (QElemPtr) &gTTimeTask);
  543.         gTotalTime = (thirtySeconds + gTTimeTask.tmCount) / 1000; //milliseconds
  544.         RunMeterAnimation();
  545.         
  546.     } while (!gFinished);
  547. }
  548.  
  549. void DoEvent (EventRecord *event)
  550. {
  551.     short        part;
  552.     WindowPtr    window;
  553.     char        key;
  554.     
  555.     //Prototypes
  556.     void AdjustMenus( void );
  557.     void DoMenuCommand(long menuResult);
  558.     void DoActivate(WindowPtr window, Boolean becomingActive);
  559.     void DoUpdate(WindowPtr window);
  560.     
  561.     switch ( event->what ) {
  562.         case mouseDown:
  563.             part = FindWindow(event->where, &window);
  564.             switch ( part ) {
  565.                 case inMenuBar:
  566.                     StopGETimer((GEWorldPtr) GetWRefCon(gAnimWindow));
  567.                     AdjustMenus();
  568.                     DoMenuCommand(MenuSelect(event->where));
  569.                     StartGETimer((GEWorldPtr) GetWRefCon(gAnimWindow));
  570.                     break;
  571.                 case inSysWindow:
  572.                     SystemClick(event, window);
  573.                     break;
  574.                 case inContent:
  575.                     if ( window != FrontWindow() ) 
  576.                         SelectWindow(window);
  577.                     if (MouseDownInSensor((GEWorldPtr) GetWRefCon(gAnimWindow), event->where))
  578.                         ;;
  579.                     break;
  580.                 case inDrag:
  581.                     DragWindow(window, event->where, &qd.screenBits.bounds);
  582.                     break;
  583.             }
  584.             break;
  585.         case keyDown:
  586.             key = event->message & charCodeMask;
  587.             if ( event->modifiers & cmdKey ) {
  588.                 StopGETimer((GEWorldPtr) GetWRefCon(gAnimWindow));
  589.                 AdjustMenus();
  590.                 DoMenuCommand(MenuKey(key));
  591.                 StartGETimer((GEWorldPtr) GetWRefCon(gAnimWindow));
  592.             }
  593.             else {
  594.                 switch (key) {
  595.                     case 'U':
  596.                     case 'u':
  597.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), 0, -50);
  598.                         break;
  599.                     case 'D':
  600.                     case 'd':
  601.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), 0, 50);
  602.                         break;
  603.                     case 'R':
  604.                     case 'r':
  605.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), 50, 0);
  606.                         break;
  607.                     case 'L':
  608.                     case 'l':
  609.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), -50, 0);
  610.                         break;
  611.                 }
  612.             }
  613.             gDoOne = true;
  614.             break;
  615.         case activateEvt:
  616.             DoActivate((WindowPtr) event->message, (event->modifiers & activeFlag) != 0);
  617.             break;
  618.         case updateEvt:
  619.             DoUpdate((WindowPtr) event->message);
  620.             break;
  621.         case osEvt:
  622.             switch ((event->message >> 24) & 0x0FF) {
  623.                 case suspendResumeMessage:
  624.                     gInBackground = (event->message & resumeFlag) == 0;
  625.                     DoActivate(FrontWindow(), !gInBackground);
  626.                     break;
  627.             }
  628.             break;
  629.         }
  630. }
  631.  
  632. void DoActivate(WindowPtr window, Boolean becomingActive)
  633. {
  634. #pragma unused (window)
  635. #pragma unused (becomingActive)
  636.     //Could start and stop animation here
  637. }
  638.  
  639.  
  640. void DoUpdate(WindowPtr window)
  641. {
  642.     Rect geRect;
  643.     GEWorldPtr geWorld;
  644.  
  645.     if (window == gAnimWindow)
  646.     {
  647.         SetPort( (GrafPtr) window );
  648.         //Protect GEWorld rect before updating window, since we will draw it
  649.         geWorld = (GEWorldPtr) GetWRefCon(gAnimWindow);
  650.         geRect = geWorld->animationRect;
  651.         RectOffset(&geRect, geWorld->worldFocus.h, geWorld->worldFocus.v);
  652.         ValidRect(&geRect);
  653.         
  654.         BeginUpdate(window);
  655.             FillRgn(((GrafPtr) window)->visRgn, qd.gray);
  656.         EndUpdate(window);
  657.         
  658.         DoWorldUpdate((GEWorldPtr) GetWRefCon(gAnimWindow), true);
  659.     }
  660. }
  661.  
  662. void AdjustMenus( void )
  663. {
  664.     WindowPtr    window;
  665.     MenuHandle    menu;
  666.     
  667.     window = FrontWindow();
  668.     
  669.     menu = GetMHandle(mFile);
  670.     EnableItem(menu, iQuit);
  671.  
  672.     menu = GetMHandle(mEdit);
  673.     if (window = gAnimWindow) {
  674.         DisableItem(menu, iUndo);
  675.         DisableItem(menu, iCut);
  676.         DisableItem(menu, iCopy);
  677.         DisableItem(menu, iClear);
  678.         DisableItem(menu, iPaste);
  679.     }
  680.     else {
  681.         EnableItem(menu, iUndo);
  682.         EnableItem(menu, iCut);
  683.         EnableItem(menu, iCopy);
  684.         EnableItem(menu, iClear);
  685.         EnableItem(menu, iPaste);
  686.     }
  687.     menu = GetMHandle(mSpecial);
  688.     //Set up special items!
  689.     CheckItem(menu, iSingleFrame, gSingleFrame);
  690.     CheckItem(menu, iGrabber, GrabberActive((GEWorldPtr) GetWRefCon(gAnimWindow)));
  691. }
  692.  
  693. void DoMenuCommand(long menuResult)
  694. {
  695.     short        menuID;
  696.     short        menuItem;
  697.     Str255        daName;
  698.     short        daRefNum;
  699.  
  700.     menuID = HiWord(menuResult);
  701.     menuItem = LoWord(menuResult);
  702.     switch ( menuID ) {
  703.         case mApple:
  704.             switch ( menuItem ) {
  705.                 case iAbout:
  706.                     DoAboutBox();
  707.                     break;
  708.                 default:            /* all other items in this menu are DAs */
  709.                     GetItem(GetMHandle(mApple), menuItem, daName);
  710.                     daRefNum = OpenDeskAcc(daName);
  711.                     break;
  712.             }
  713.             break;
  714.         case mFile:
  715.             if (menuItem == iQuit)
  716.                 gFinished = true;
  717.             break;
  718.         case mEdit:
  719.             (void) SystemEdit(menuItem-1);
  720.             break;
  721.         case mSpecial:
  722.             //Add special items
  723.             switch ( menuItem ) {
  724.                 case iShoot:
  725.                     ShootCannon((GEWorldPtr) GetWRefCon(gAnimWindow), sensorOn);
  726.                     break;
  727.                 case iSingleFrame:
  728.                     gSingleFrame = !gSingleFrame;
  729.                     break;
  730.                 case iSignText:
  731.                     DoSetSignText();
  732.                     break;
  733.                 case iSpeed:
  734.                     DoSetSpeed();
  735.                     break;
  736.                 case iGrabber:
  737.                     ActivateGrabber((GEWorldPtr) GetWRefCon(gAnimWindow), 
  738.                                     !GrabberActive((GEWorldPtr) GetWRefCon(gAnimWindow)));
  739.                     break;
  740.             }
  741.             break;
  742.     }
  743.     HiliteMenu(0);
  744. }
  745.  
  746. //Utility routines
  747.  
  748.  
  749. void AdjustCursor( void )
  750. {
  751.     WindowPtr    window;
  752.     
  753.     window = FrontWindow();
  754.     
  755.     if ( (window == gAnimWindow) && (!gInBackground) ) {
  756.         SetCursor(&qd.arrow);
  757.     }
  758. }
  759.  
  760.